/*
* Author: Chris Seguin
*
* This software has been developed under the copyleft
* rules of the GNU General Public License. Please
* consult the GNU General Public License for more
* details about use and distribution of this software.
*/
package org.acm.seguin.summary;
import org.acm.seguin.parser.ast.ASTAssignmentOperator;
import org.acm.seguin.parser.ast.ASTExpression;
import org.acm.seguin.parser.ast.ASTName;
import org.acm.seguin.parser.ast.ASTStatementExpression;
import org.acm.seguin.parser.ast.SimpleNode;
import org.acm.seguin.summary.query.GetTypeSummary;
/**
* Summarize a field access summary.
*
*@author Chris Seguin
*@author Achille Petrilli, mods to distinguish read from write access
*@created June 23, 1999
*/
public class FieldAccessSummary extends Summary {
// Instance Variables
private String objectName;
private String packageName;
private String fieldName;
private boolean isAssignment;
/**
* Creates a field access summary from an ASTName object.
*
*@param parentSummary the parent summary
*@param nameNode the ASTName object
*/
public FieldAccessSummary(Summary parentSummary, ASTName nameNode)
{
// Initialize the parent class
super(parentSummary);
// Initialize the variables
fieldName = null;
objectName = null;
packageName = null;
isAssignment = checkAssignment(nameNode);
// Local Variables
int numChildren = nameNode.getNameSize();
// Determine the name of the message
fieldName = nameNode.getNamePart(numChildren - 1).intern();
// Determine the name of the object (or class)
if (numChildren > 1) {
objectName = nameNode.getNamePart(numChildren - 2).intern();
// Extract the package
if (numChildren > 2) {
StringBuffer buffer = new StringBuffer(nameNode.getNamePart(0));
for (int ndx = 1; ndx < numChildren - 2; ndx++) {
buffer.append(".");
buffer.append(nameNode.getNamePart(ndx));
}
packageName = buffer.toString().intern();
}
}
}
/**
* Gets the Assignment attribute of the FieldAccessSummary object
*
*@return The Assignment value
*/
public boolean isAssignment()
{
return isAssignment;
}
/**
* Get the package name
*
*@return a string containing the name of the package
*/
public String getPackageName()
{
return packageName;
}
/**
* Get the name of the type
*
*@return a string containing the name of the type
*/
public String getObjectName()
{
return objectName;
}
/**
* Get the name of the field
*
*@return a string containing the name of the field
*/
public String getFieldName()
{
return fieldName;
}
/**
* Gets a type declaration if this reference is to a package and type pair
*
*@return the summary
*/
public TypeDeclSummary getTypeDecl()
{
if (packageName == null) {
if (objectName != null) {
TypeDeclSummary result = new TypeDeclSummary(this, packageName, objectName);
TypeSummary test = GetTypeSummary.query(result);
if (test != null) {
return result;
}
}
return null;
}
return new TypeDeclSummary(this, packageName, objectName);
}
/**
* Gets the FirstObject attribute of the FieldAccessSummary object
*
*@return The FirstObject value
*/
public String getFirstObject()
{
String name = getName();
int index = name.indexOf(".");
if (index == -1) {
return name;
}
else {
return name.substring(0, index);
}
}
/**
* Gets the Name attribute of the FieldAccessSummary object
*
*@return The Name value
*/
public String getName()
{
// Start with the long name
StringBuffer buffer = new StringBuffer();
if (packageName != null) {
buffer.append(packageName);
buffer.append(".");
}
if (objectName != null) {
buffer.append(objectName);
buffer.append(".");
}
buffer.append(fieldName);
return buffer.toString();
}
/**
* Convert this into a string
*
*@return a string representation of the type
*/
public String toString()
{
// Start with the long name
StringBuffer buffer = new StringBuffer();
if (packageName != null) {
buffer.append(packageName);
buffer.append(".");
}
if (objectName != null) {
buffer.append(objectName);
buffer.append(".");
}
buffer.append(fieldName);
if (isAssignment) {
buffer.append("-W");
}
return buffer.toString();
}
/**
* Provide method to visit a node
*
*@param visitor the visitor
*@param data the data for the visit
*@return some new data
*/
public Object accept(SummaryVisitor visitor, Object data)
{
return visitor.visit(this, data);
}
/**
* Check to see if it is equal
*
*@param other the other item
*@return true if they are equal
*/
public boolean equals(Object other)
{
if (other instanceof FieldAccessSummary) {
FieldAccessSummary fas = (FieldAccessSummary) other;
boolean sameObject = ((objectName == null) && (fas.objectName == null)) ||
((objectName != null) && objectName.equals(fas.objectName));
boolean samePackage = ((packageName == null) && (fas.packageName == null)) ||
((packageName != null) && packageName.equals(fas.packageName));
boolean sameField = ((fieldName == null) && (fas.fieldName == null)) ||
((fieldName != null) && fieldName.equals(fas.fieldName));
return sameObject && samePackage && sameField && (isAssignment == fas.isAssignment);
}
return super.equals(other);
}
/**
* Gets the ChildIndex attribute of the FieldAccessSummary object
*
*@param parent Description of Parameter
*@param child Description of Parameter
*@return The ChildIndex value
*/
private int getChildIndex(SimpleNode parent, SimpleNode child)
{
for (int i = 0; i < parent.jjtGetNumChildren(); i++) {
if (parent.jjtGetChild(i) == child) {
return i;
}
}
return -1;
}
/**
* Description of the Method
*
*@param node Description of Parameter
*@return Description of the Returned Value
*/
private boolean checkAssignment(SimpleNode node)
{
SimpleNode previous = node;
for (SimpleNode current = (SimpleNode) node.jjtGetParent();
current != null;
current = (SimpleNode) current.jjtGetParent()) {
int nodeIdx = getChildIndex(current, previous);
if (nodeIdx == -1) {
throw new IllegalArgumentException("Child node not found into its parent ???");
}
if (current.jjtGetNumChildren() > (nodeIdx + 1)) {
if (current instanceof ASTStatementExpression || current instanceof ASTExpression) {
if (current.jjtGetChild(nodeIdx + 1) instanceof ASTAssignmentOperator) {
return true;
}
else {
return false;
}
}
}
previous = current;
}
return false;
}
}